home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / prog_c / cuj0696.zip / DWYER.ZIP / COUPON.TST / SETCUPN.C < prev    next >
C/C++ Source or Header  |  1996-01-08  |  8KB  |  219 lines

  1. /* ============ */
  2. /* setcupn.c    */
  3. /* ============ */
  4. #include <defcodes.h>
  5. #include <miscdefs.h>
  6. #include <cupndefs.h>
  7. #include <math.h>
  8.  
  9. #define    ACT(X)    #X
  10.  
  11. #define    CLAMP(Var, Lo, Hi)    __min(Hi, __max(Lo, Var))
  12.  
  13. #define    NEED_MAX_CPN_LEN(LO, HI) \
  14.     "Enter Maximum Segment Length ["ACT(LO)"-"ACT(HI)"]: "
  15.  
  16. #define    NEED_MIN_CELL_EXPECT(LO, HI) \
  17.     "Enter Minimum Cell Expectation ["ACT(LO)"-"ACT(HI)"]: "
  18.  
  19. #define    NEED_NUMBER_COUPONS(LO, HI) \
  20.     "Enter Number of Coupons to be Collected ["\
  21.         ACT(LO)"-"ACT(HI)"]: "
  22.  
  23. #define    NEED_UNIQUE_COUPON_INTEGERS(LO, HI) \
  24.     "Enter Number Unique Integers in a Coupon ["\
  25.         ACT(LO)"-"ACT(HI)"]: "
  26.  
  27. #define    REPORT_USER_INT_ENTRY(Entry, Label)        \
  28.     {                            \
  29.     fflush(NULL); printf("\n");            \
  30.     printf("\tNumber Entered:  %.f", (double)Entry);\
  31.     printf(" (%s)\n", Label);            \
  32.     }
  33. #define    SHOW_INT_VALUE_USED(Entered, Used)             \
  34.     printf("\tTest Value Used: %.f%s\n", (double)Used,    \
  35.     ((double)Entered == (double)Used) ? "" : " (Clamped)")
  36.  
  37. /* ------------------- */
  38. /* FUNCTION PROTOTYPES */
  39. /* ------------------- */
  40. # undef F
  41. # if defined(__STDC__) || defined(__PROTO__)
  42. #    define  F( P )  P
  43. # else
  44. #    define  F( P )  ()
  45. # endif
  46.  
  47. /* INDENT OFF */
  48. static    void    CupnMeanStdDev F((unsigned int, double *, double *));
  49. extern    void    SetCouponControls F((COUPON_DATA_STRU *));
  50.  
  51. # undef F
  52. /* INDENT ON */
  53.  
  54. static    double    CellExpect[MAX_COUPON_LEN];
  55. static    double    CouponProbs[MAX_COUPON_LEN];
  56. /* ==================================================================== */
  57. /*  SetCouponControls - Puts Run Controls in CouponData structure    */
  58. /* ==================================================================== */
  59. void
  60. SetCouponControls(COUPON_DATA_STRU *CouponData)
  61. {
  62.     int     k, NewlineCh;
  63.     char    Prompt[64];
  64.     int     UserIntEntry;
  65.     long    UserLongEntry;
  66.  
  67.     NewlineCh = _isatty(_fileno(stdin)) ? '\r' : '\n';
  68.  
  69.     /* ------------------------------------- */
  70.     /* Request Number Integers in Coupon Set */
  71.     /* ------------------------------------- */
  72.     GetInt(NEED_UNIQUE_COUPON_INTEGERS(MIN_SET_SIZE, MAX_SET_SIZE),
  73.     &UserIntEntry);
  74.  
  75.     REPORT_USER_INT_ENTRY(UserIntEntry,
  76.     "Number Unique Integers in a Coupon");
  77.  
  78.     CouponData->SetSize = CLAMP(UserIntEntry, MIN_SET_SIZE, MAX_SET_SIZE);
  79.  
  80.     SHOW_INT_VALUE_USED(UserIntEntry, CouponData->SetSize);
  81.  
  82.     fflush(NULL);fprintf(stderr, "%c", NewlineCh);
  83.     /* ------------------------------------------- */
  84.     /* Request Maximum Coupon Length to be Tallied */
  85.     /* ------------------------------------------- */
  86.     {
  87.     int    MinCpnLen = CouponData->SetSize + 6;
  88.  
  89.     sprintf(Prompt, "Enter Maximum Segment Length [%d-%d]: ",
  90.         MinCpnLen, MAX_COUPON_LEN);
  91.  
  92.     GetInt(Prompt, &UserIntEntry);
  93.  
  94.     REPORT_USER_INT_ENTRY(UserIntEntry, "Maximum Segment Length");
  95.  
  96.     CouponData->MaxCpnLen =
  97.         CLAMP(UserIntEntry, MinCpnLen, MAX_COUPON_LEN);
  98.  
  99.     SHOW_INT_VALUE_USED(UserIntEntry, CouponData->MaxCpnLen);
  100.     }
  101.     fflush(NULL);fprintf(stderr, "%c", NewlineCh);
  102.     /* -------------------------------------- */
  103.     /* Calculate & Store Number of Categories */
  104.     /* -------------------------------------- */
  105.     CouponData->NumCategories =
  106.     CouponData->MaxCpnLen - CouponData->SetSize + 1;
  107.  
  108.     /* -------------------------------- */
  109.     /* Request Minimum Cell Expectation    */
  110.     /* -------------------------------- */
  111.     GetInt(NEED_MIN_CELL_EXPECT(MIN_CELL_XPCT, MAX_CELL_XPCT),
  112.     &UserIntEntry);
  113.  
  114.     REPORT_USER_INT_ENTRY(UserIntEntry, "Minimum Cell Expectation");
  115.  
  116.     /* ---------------- */
  117.     /* Clamp CellExpect */
  118.     /* ---------------- */
  119.     CouponData->UserCellExpect =
  120.     __min(MAX_CELL_XPCT, __max(MIN_CELL_XPCT, UserIntEntry));
  121.  
  122.     SHOW_INT_VALUE_USED(UserIntEntry, CouponData->UserCellExpect);
  123.  
  124.     fflush(NULL);fprintf(stderr, "%c", NewlineCh);
  125.     /* ----------------------------------------------------------- */
  126.     /* Calculate Probabilities Based on Data Width & Coupon Length */
  127.     /* ----------------------------------------------------------- */
  128.     CalcCouponProbs(CouponData->SetSize, CouponData->MaxCpnLen,
  129.     CouponProbs);
  130.  
  131.     /* ------------------------------------------------------ */
  132.     /* Compute Number Coupons Needed to Deliver Ideal Minimum */
  133.     /* ------------------------------------------------------ */
  134.     CouponData->IdealNumCoupons = (long)
  135.     ceil((double)MIN_CELL_XPCT/CouponProbs[0]);
  136.  
  137.     /* ------------------------------------------------------ */
  138.     /* Compute Number Coupons Needed to Deliver Users Minimum */
  139.     /* ------------------------------------------------------ */
  140.     CouponData->UserNumCoupons = (long)
  141.     ceil(CouponData->UserCellExpect/CouponProbs[0]);
  142.  
  143.     /* ---------------------------------------------------- */
  144.     /* Get User-Specified Number of Coupons to Be Collected */
  145.     /* ---------------------------------------------------- */
  146.     sprintf(Prompt, "How Many Coupons Are To Be Collected?"
  147.     "  [%ld ...]: ",
  148.     (long)__max(MIN_NUM_COUPONS, CouponData->UserNumCoupons));
  149.  
  150.     GetLong(Prompt, &UserLongEntry);
  151.  
  152.     REPORT_USER_INT_ENTRY(UserLongEntry,
  153.     "Number of Coupons to be Counted");
  154.  
  155.     CouponData->NumCoupons = (int)
  156.     CLAMP(UserLongEntry, MIN_NUM_COUPONS, MAX_NUM_COUPONS);
  157.  
  158.     SHOW_INT_VALUE_USED(UserLongEntry, CouponData->NumCoupons);
  159.  
  160.     fflush(NULL);fprintf(stderr, "%c", NewlineCh);
  161.     /* -------------------------------------------------- */
  162.     /* Calculate Cell Expectations Based on Probabilities */
  163.     /* -------------------------------------------------- */
  164.     for (k = 0; k < CouponData->NumCategories; ++k)
  165.     {
  166.     CellExpect[k] = CouponProbs[k] * CouponData->NumCoupons;
  167.     P(printf("CellExpect[%2d] = %.11g\n", k, CellExpect[k]));
  168.     }
  169.     /* -------------------------------------------------- */
  170.     /* Lump lower-valued categories into next higher ones */
  171.     /* -------------------------------------------------- */
  172.     CouponData->NotEnough = 0;
  173.     for (k = 0; k < CouponData->NumCategories - 1; ++k)
  174.     {
  175.     if (CellExpect[k] < CouponData->UserCellExpect)
  176.     {
  177.         ++CouponData->NotEnough;
  178.         CellExpect[k+1] += CellExpect[k];
  179.         CellExpect[k]    = 0;
  180.     }
  181.     }
  182.    CouponData->CellExpect = CellExpect;
  183.  
  184.     /* ------------------------------ */
  185.     /* Set Generator Failure Count to */
  186.     /* A Priori Mean + 6 * Std Dev.   */
  187.     /* ------------------------------ */
  188.     {
  189.     double    CpnMean, CpnStdDev;
  190.  
  191.     CupnMeanStdDev(CouponData->SetSize, &CpnMean, &CpnStdDev);
  192.  
  193.     CouponData->MaxGenPerSeg = (long)
  194.         (ceil(CpnMean) +
  195.         100 * ceil(CpnStdDev));
  196.     }
  197.     printf("\nFailure Count = %ld\n", CouponData->MaxGenPerSeg);
  198.     printf("\tA Complete Coupon Should Have Been\n"
  199.        "\tCollected Within This Many Variates.\n");
  200.     P(printf("NotEnough = %d\n", CouponData->NotEnough));
  201.     CouponData->CallStatusOK = (CouponData->NotEnough == 0);
  202. }
  203. /* ==================================================================== */
  204. /* CupnMeanStdDev - Calculates Coupon-Width Mean & Standard Deviation    */
  205. /* ==================================================================== */
  206. static    void
  207. CupnMeanStdDev(UINT Width, double *Mean, double *StdDev)
  208. {
  209.     /* --------------------------------------------------------- */
  210.     /* Width is maximum number of unique integers in a data set. */
  211.     /* These equations were taken from D. E. Knuth, "The Art of  */
  212.     /* Computer Programming," Volume 2, Seminumerical Algorithms */
  213.     /* (1981), page 536 (top).                     */
  214.     /* --------------------------------------------------------- */
  215.     *Mean   = Width * (CalcHarm(1, Width) - 1);
  216.     *StdDev = sqrt(SQR((double)Width) * (CalcHarm(2, Width) - 1)
  217.         - *Mean);
  218. }
  219.